Skip to content

Improve withinSessionLevelLock: invoke callback only on successful lo…#24

Merged
antonkomarev merged 3 commits into
masterfrom
feature/within-session-lock-callback-only-on-success
Feb 9, 2026
Merged

Improve withinSessionLevelLock: invoke callback only on successful lo…#24
antonkomarev merged 3 commits into
masterfrom
feature/within-session-lock-callback-only-on-success

Conversation

@antonkomarev
Copy link
Copy Markdown
Member

This PR improves the withinSessionLevelLock() API by invoking the callback only when the lock is successfully acquired, eliminating the need for manual wasAcquired checks inside the callback.

Before

$result = $locker->withinSessionLevelLock($conn, $key, function ($handle) {
    if (!$handle->wasAcquired) {
        return null; // Consumer must check inside callback
    }
    return processOrder();
}, $timeout);

### After
```php
$handle = $locker->withinSessionLevelLock($conn, $key, fn() => processOrder(), $timeout);

if ($handle->wasAcquired) {
    echo $handle->result; // Result of callback
} else {
    // Lock not acquired, callback was not invoked
}

Key improvements

  1. Callback only on success — The callback is invoked only when the lock is acquired. If the lock is held by another process, the callback is skipped and wasAcquired = false.

  2. Cleaner API — Consumer checks wasAcquired outside the callback, not inside. The callback can focus solely on the critical section logic.

  3. New return type — Returns WithinSessionLevelLockHandle with:

    • wasAcquired: bool — Whether the lock was acquired
    • result: mixed — Result of the callback (null if lock not acquired)
  4. Simpler callback signature — Callback no longer receives SessionLevelLockHandle argument, since it's only invoked when the lock is held.

…ck acquisition

- Change withinSessionLevelLock() to invoke callback only when lock is acquired
- Return WithinSessionLevelLockHandle with wasAcquired flag and callback result
- Callback no longer receives SessionLevelLockHandle argument
- Update all tests to check wasAcquired outside callback
- Add test verifying callback is not invoked when lock is not acquired

BREAKING CHANGE: withinSessionLevelLock() return type changed from mixed to WithinSessionLevelLockHandle
…nLevelLock

- Add docblock warning that LockReleaseException guarantees successful callback but loses return value
- Update ADR-003 with 'Known limitation' section explaining PHP finally semantics
- Suggest WithinSessionLockReleaseException as potential future improvement
- Direct users to low-level API for cases where callback result must be preserved
- Test verifies that LockReleaseException is thrown when callback succeeds but release fails
- Confirms callback result is lost in this scenario (documented limitation in ADR-003)
- Uses PG_TERMINATE_BACKEND to simulate release failure
- All 94 tests pass
@antonkomarev antonkomarev merged commit f27aabd into master Feb 9, 2026
2 checks passed
@antonkomarev antonkomarev deleted the feature/within-session-lock-callback-only-on-success branch February 9, 2026 05:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant